package j.framework.tags.easyui;

import j.util.StringUtils;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import java.io.IOException;

/**
 * easyui版的form tag
 * 保存数据时，将向后台的提交的参数有：deletedIds,updatedRows,insertedRows
 * User: jason
 * Date: 2015/1/16 14:59
 */
public class EditableDataGridTag extends BodyTagSupport {
    //dataGrid id
    private String id;

    /**
     * 获取数据的地址
     * 地址必须是绝对路径的地址，若不是，则增加MemberStatus.LOGIN_FILTER_PREFIX_NAME为前缀
     */
    private String getDataUrl;

    //保存数据的url
    private String saveDataUrl;

    private String idPropertyName;//若需要删除，需要指定此属性，否则无法取出来待删除的行

    /**
     * 在提交数据之前所调用的方法
     * 方法签名：beforeSaveDataEvent($dg,insertedRows,updatedRows,deletedIds);
     * 此方法可返回一个json对象，此json对象也将一并提交到后台
     */
    private String beforeSaveDataEvent;

    /**
     * 保存数据成功后所调用的事件
     * 方法签名：saveDataSuccessEvent(data);//data为数据库端返回的数据
     */
    private String saveDataSuccessEvent;

    //选项参数
    private String dataOptions;

    private String toolbarId;

    private boolean singleSelected = true;

    //是否支持增加
    private boolean insertSupported = true;

    /**
     * 增加时，行数据的默认值，必须符合json数据格式，形如：{key:value}
     */
    private String defaultRowData;

    //是否支持删除
    private boolean deleteSupported = true;

    //是否增加关闭窗口的按钮
    private boolean addCloseWindowButton;

    /**
     * 验证编辑行数据的事件，可自行定义
     * 方法签名：validateRow($dg,editIndex);
     */
    private String validateRowEvent;


    @Override
    public int doStartTag() throws JspException {
        JspWriter writer = this.pageContext.getOut();
        try{
            writer.write("<table id=\"");
            writer.write(id);
            writer.write("\" style=\"width:100%;\" class=\"easyui-datagrid\" data-options=\"fit:true,");
            if(StringUtils.isNotEmpty(getDataUrl)){
                writer.write("url:'");
                writer.write(getDataUrl);
                writer.write("',");
            }
            //构造toolbar
            String toolbarId = this.toolbarId;
            if(StringUtils.isNullOrEmpty(toolbarId)){
                toolbarId = id+"Tb";
            }
            writer.write("toolbar:'#");
            writer.write(toolbarId);
            writer.write("',");
            //onDblClickRow
            writer.write("onDblClickRow:onDblClickRow,");
            //onClickRow
            writer.write("onClickRow:onClickRow,");
            //是否单选
            writer.write("singleSelect:");
            writer.write(singleSelected?"true":"false");
            if(StringUtils.isNotEmpty(dataOptions)){
                writer.write(",");
                writer.write(dataOptions);
            }
            writer.write("\"><thead>");
            writer.flush();
        }catch (IOException e){
            throw new JspException(e.getMessage());
        }
        return EVAL_BODY_INCLUDE;
    }

    @Override
    public int doAfterBody() throws JspException {
        JspWriter writer = this.pageContext.getOut();
        try {
            writer.write("</thead></table>");
            //构造toolbar
            if(StringUtils.isNullOrEmpty(toolbarId)){
                writer.write("<div id=\"");
                writer.write(this.id);
                writer.write("Tb\">");
                //增加按钮
                if(insertSupported){
                    writer.write("<a href=\"javascript:void(0);\" class=\"easyui-linkbutton\" onclick=\"do");
                    writer.write(id);
                    writer.write("Add();\" data-options=\"iconCls:'icon-add'\">增加</a> ");
                }
                //删除按钮
                if(deleteSupported){
                    writer.write("<a href=\"javascript:void(0);\" class=\"easyui-linkbutton\" onclick=\"do");
                    writer.write(id);
                    writer.write("Delete();\" data-options=\"iconCls:'icon-remove'\">删除</a> ");
                }
                //保存按钮
                writer.write("<a href=\"javascript:void(0);\" class=\"easyui-linkbutton\" onclick=\"do");
                writer.write(id);
                writer.write("Save();\" data-options=\"iconCls:'icon-save'\">保存</a> ");
                //放弃修改按钮
                writer.write("<a href=\"javascript:void(0);\" class=\"easyui-linkbutton\" onclick=\"do");
                writer.write(id);
                writer.write("Reject();\" data-options=\"iconCls:'icon-undo'\">放弃修改</a> ");
                //返回按钮
                if(addCloseWindowButton){
                    writer.write("<a href=\"javascript:void(0);\" class=\"easyui-linkbutton\" onclick=\"closeThisDialog();\" data-options=\"iconCls:'icon-undo'\">返回</a>");
                }
                //toolbar结束
                writer.write("</div>");
                writer.flush();
                // 开始构造必要的javascript语句
                writer.write("\n<script>");
                writer.write("var editIndex = undefined;\n" +
                        "      var deletedIds = null;\n" +
                        "      var insertedRows = null;\n" +
                        "      var updatedRows = null;\n" +
                        "      function endEditing(){\n" +
                        "          if (editIndex == undefined){return true;}\n" +
                        "          var $dg = $(\"#"+id+"\");\n" +
                        "          if ($dg.datagrid('validateRow', editIndex)){\n");
                if(StringUtils.isNotEmpty(validateRowEvent)){
                    writer.write("if(!"+validateRowEvent+"($dg,editIndex)){return false;}\n");
                }
                writer.write("         $dg.datagrid('endEdit', editIndex);\n" +
                        "              editIndex = undefined;\n" +
                        "              return true;\n" +
                        "          }\n" +
                        "          return false;\n" +
                        "      }");
                //行的双击事件，双击为编辑行
                writer.write("function onDblClickRow(index){\n" +
                        "          var $dg = $(\"#"+id+"\");\n" +
                        "          if (editIndex != index){\n" +
                        "              if (endEditing()){\n" +
                        "                  $dg.datagrid('selectRow', index).datagrid('beginEdit', index);\n" +
                        "                  editIndex = index;\n" +
                        "              } else {\n" +
                        "                  $dg.datagrid('selectRow', editIndex);\n" +
                        "              }\n" +
                        "          }\n" +
                        "      }");
                //行的单击事件，若当前正处于编辑状态，若行验证通过，则结束当前行的编辑状态
                writer.write("function onClickRow(index){\n" +
                        "          if(editIndex!=index){\n" +
                        "              if(!endEditing()){\n" +
                        "                  alert(\"编辑的行没有通过验证，请检查！\");\n" +
                        "              }\n" +
                        "          }\n" +
                        "      }");
                //增加按钮的事件
                if(insertSupported){
                    writer.write("function do");
                    writer.write(id);
                    writer.write("Add(){\n" +
                            "          //先结束当前的编辑\n" +
                            "          if(endEditing()){\n" +
                            "              var $dg = $(\"#"+id+"\");var rowData = {};\n");
                    if(StringUtils.isNotEmpty(defaultRowData)){
                        writer.write("rowData = "+defaultRowData+";");
                    }
                    writer.write("              $dg.datagrid('appendRow',rowData);\n" +
                            "              editIndex = $dg.datagrid('getRows').length;\n" +
                            "              if(editIndex){\n" +
                            "                  editIndex -= 1 ;\n" +
                            "              }\n" +
                            "              $dg.datagrid('selectRow', editIndex).datagrid('beginEdit', editIndex);\n" +
                            "          }else{\n" +
                            "              alert(\"编辑的行没有通过验证，请检查！\");\n" +
                            "          }\n" +
                            "      }");
                }
                //删除按钮的事件
                if(deleteSupported){
                    writer.write("function do");
                    writer.write(id);
                    writer.write("Delete(){\n" +
                            "          var $dg = $(\"#"+id+"\");\n" +
                            "          var row = $dg.datagrid(\"getSelected\");\n" +
                            "          if(!row){\n" +
                            "              alert(\"请选择要删除的数据行！\");\n" +
                            "              return;\n" +
                            "          }\n" +
                            "          var rowIndex = $dg.datagrid(\"getRowIndex\",row);\n" +
                            "          if(!endEditing()){\n" +
                            "            //取消本行的修改\n" +
                            "              $dg.datagrid(\"cancelEdit\",rowIndex);\n" +
                            "              editIndex = undefined;\n" +
                            "          }\n" +
                            "          if(window.confirm(\"你确认？\")){\n" +
                            "              $dg.datagrid(\"deleteRow\",rowIndex);\n" +
                            "          }\n" +
                            "      }");
                }
                //放弃按钮的事件
                writer.write("function do");
                writer.write(id);
                writer.write("Reject(){\n" +
                        "          var $dg = $(\"#"+id+"\");\n" +
                        "          if(isHasUpdatedData($dg)){\n" +
                        "              if(window.confirm(\"你确认要放弃本次的所有修改吗？\")){\n" +
                        "                  $dg.datagrid('rejectChanges');\n" +
                        "                  editIndex = undefined;\n" +
                        "              }\n" +
                        "          }else{\n" +
                        "              alert(\"现在没有任何数据做出修改！\");if(editIndex!=undefined){$dg.datagrid('endEdit', editIndex);editIndex=undefined;}\n" +
                        "          }\n" +
                        "          deletedIds = null;\n" +
                        "          insertedRows = null;\n" +
                        "          updatedRows = null;\n" +
                        "      }");
                //判断有无数据修改（包含增加、修改的、删除的）
                writer.write("function isHasUpdatedData($dg){\n" +
                        "          var rows = $dg.datagrid('getChanges',\"deleted\");\n" +
                        "          deletedIds = \"\";\n" +
                        "          if(rows && rows.length>0){\n" +
                        "              $(rows).each(function(i,item){\n" +
                        "                  deletedIds += item[\""+idPropertyName+"\"]+\",\";\n" +
                        "              });\n" +
                        "          }\n" +
                        "          //获取新增的行\n" +
                        "          insertedRows = $dg.datagrid(\"getChanges\",\"inserted\");\n" +
                        "          //再获取更新的行\n" +
                        "          updatedRows = $dg.datagrid('getChanges',\"updated\");\n" +
                        "          if(deletedIds === \"\" && (insertedRows == null || insertedRows.length==0) &&\n" +
                        "                  (updatedRows == null || updatedRows.length==0)){\n" +
                        "              //没有更新任何行，也没有删除任何行\n" +
                        "              return false;\n" +
                        "          }\n" +
                        "          return true;\n" +
                        "      }");
                //保存
                String saveUrl = saveDataUrl;
                if(StringUtils.isNullOrEmpty(saveUrl)){
                    throw new JspException("editableDataGrid必须指定saveDataUrl参数！");
                }
                if(!saveUrl.startsWith("/")){
                    saveUrl = "/user/"+saveUrl;
                }
                writer.write("function do"+id+"Save(){\n" +
                        "          if(!endEditing()){\n" +
                        "              alert(\"编辑的行没有通过验证，请检查！\");\n" +
                        "              return;\n" +
                        "          }\n" +
                        "          var $dg = $(\"#"+id+"\");\n" +
                        "          if(isHasUpdatedData($dg,true)){\nvar postedData = {};\n");
                if(StringUtils.isNotEmpty(beforeSaveDataEvent)){
                    //方法签名：beforeSaveDataEvent($dg,insertedRows,updatedRows,deletedIds);
                    writer.write("         var ret = "+beforeSaveDataEvent+"($dg,insertedRows,updatedRows,deletedIds);\n");
                    writer.write("         if(ret){postedData=ret;}");
                }
                writer.write("var params = {deletedIds:deletedIds,updatedRows:JSON.stringify(updatedRows),insertedRows:JSON.stringify(insertedRows)};");

                writer.write("             Http.post(\""+saveUrl+"\",j.mergeJson(postedData,params),function(data){\n" +
                        "                  alert(\"保存成功！\");\n" +
                        "                  $dg.datagrid('acceptChanges');$dg.datagrid('load');\n");
                if(StringUtils.isNotEmpty(this.saveDataSuccessEvent)){
                    writer.write(this.saveDataSuccessEvent+"(data);\n");
                }
                writer.write("              });\n" +
                        "          }else{\n" +
                        "              alert(\"您没有做出任何修改，不必保存！\");\n" +
                        "          }\n" +
                        "          deletedIds = null;\n" +
                        "          insertedRows = null;\n" +
                        "          updatedRows = null;\n" +
                        "      }");
                //从json数组中找出id对应的text值
                writer.write("function getTextById(datas,id){\n" +
                        "            var text = \"\";\n" +
                        "            $(datas).each(function(i,item){\n" +
                        "                if(item.id == id){\n" +
                        "                    text = item.text;\n" +
                        "                    return false;\n" +
                        "                }\n" +
                        "            });\n" +
                        "            return text;\n" +
                        "        }");
                //关闭窗口
                writer.write("function closeThisDialog(){\n" +
                        "          var $dg = $(\"#"+id+"\");\n" +
                        "          if(isHasUpdatedData($dg)){\n" +
                        "              if(window.confirm(\"此次修改还没有保存，您确认要放弃本次修改吗？\")){\n" +
                        "                  window.close();\n" +
                        "              }\n" +
                        "          }else{\n" +
                        "              window.close();\n" +
                        "          }\n" +
                        "          deletedIds = null;\n" +
                        "          insertedRows = null;\n" +
                        "          updatedRows = null;\n" +
                        "      }");
                writer.write("</script>");
                writer.flush();
            }
        }catch (IOException e){
            throw new JspException(e.getMessage());
        }
        return SKIP_BODY;
    }

    @Override
    public int doEndTag() throws JspException {
        return EVAL_PAGE;
    }

    @Override
    public void setId(String id) {
        this.id = id;
    }

    public void setIdPropertyName(String idPropertyName) {
        this.idPropertyName = idPropertyName;
    }

    public void setGetDataUrl(String getDataUrl) {
        this.getDataUrl = getDataUrl;
    }

    public void setSaveDataUrl(String saveDataUrl) {
        this.saveDataUrl = saveDataUrl;
    }

    public void setBeforeSaveDataEvent(String beforeSaveDataEvent) {
        this.beforeSaveDataEvent = beforeSaveDataEvent;
    }

    public void setSaveDataSuccessEvent(String saveDataSuccessEvent) {
        this.saveDataSuccessEvent = saveDataSuccessEvent;
    }

    public void setDataOptions(String dataOptions) {
        this.dataOptions = dataOptions;
    }

    public void setToolbarId(String toolbarId) {
        this.toolbarId = toolbarId;
    }

    public void setSingleSelected(boolean singleSelected) {
        this.singleSelected = singleSelected;
    }

    public void setInsertSupported(boolean insertSupported) {
        this.insertSupported = insertSupported;
    }

    public void setDefaultRowData(String defaultRowData) {
        this.defaultRowData = defaultRowData;
    }

    public void setDeleteSupported(boolean deleteSupported) {
        this.deleteSupported = deleteSupported;
    }

    public void setAddCloseWindowButton(boolean addCloseWindowButton) {
        this.addCloseWindowButton = addCloseWindowButton;
    }

    public void setValidateRowEvent(String validateRowEvent) {
        this.validateRowEvent = validateRowEvent;
    }
}
